package org.water.common.bind.method;

import java.io.IOException;
import java.util.List;
import java.util.TimeZone;

import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.water.base.entity.ResultBaseBean;
import org.water.common.bind.annotation.ResultFormat;
import org.water.common.conveter.XmlDateConverter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.basic.DateConverter;
/**
 * 解析返回数据
 * @author qzy
 *
 */
public class ReulstFormatReturnValueHandler implements HandlerMethodReturnValueHandler {

	private static Logger logger=LogManager.getLogger(ReulstFormatReturnValueHandler.class);
	
	/**
	 * jsonp回调方法 参数名
	 */
	private static String CALL_BACK="callback";
	/**
	 * 日期格式
	 */
	private static String dateFormat="yyyy-MM-dd HH:mm:ss"; 
	/**
	 * 转换数据时，包名需要设置为空
	 */
	private String[] packageNameToEmptys={};
	/**
	 * xml转换器
	 */
	private static XStream xstream;
	
	/**
	 * 构造函数
	 */
	public ReulstFormatReturnValueHandler() {
		configXstream();
	}
	/**
	 * 构造函数
	 * @param dateFormat 日期格式
	 */
	public ReulstFormatReturnValueHandler(String dateFormat) {
		if(dateFormat!=null)
		{
			this.dateFormat=dateFormat;
		}
		configXstream();
	}
	/**
	 * 构造函数
	 * @param dateFormat 日期格式
	 */
	public ReulstFormatReturnValueHandler(String dateFormat,String[] packageNames) {
		if(dateFormat!=null)
		{
			this.dateFormat=dateFormat;
		}
		if(packageNames!=null)
		{
			this.packageNameToEmptys=packageNames;
		}
		configXstream();
	}

	@Override
	public void handleReturnValue(Object obj, MethodParameter methodparameter,
			ModelAndViewContainer modelandviewcontainer, NativeWebRequest nativewebrequest) throws Exception {
		modelandviewcontainer.setRequestHandled(true);
		String accept=nativewebrequest.getHeader("Accept");
		HttpServletResponse response=nativewebrequest.getNativeResponse(HttpServletResponse.class);
		setResultValue(accept,obj,nativewebrequest,response);
	}
	/**
	 * 设置返回结果值
	 * @param accept
	 * @param requestUrl
	 * @param obj
	 * @param response
	 * @throws IOException
	 */
	public void setResultValue(String accept,Object obj,NativeWebRequest request,HttpServletResponse response) throws IOException
	{
		String lastfix="",requestUrl="",jsonpFun=request.getParameter(CALL_BACK);
		if(request instanceof ServletWebRequest) requestUrl=((ServletWebRequest) request).getRequest().getServletPath();
		if(requestUrl.contains(".")) lastfix=requestUrl.substring(requestUrl.lastIndexOf(".")+1);
		if("xml".equalsIgnoreCase(lastfix))  //xml结果
		{
			setResponseResult(response,"xml",obj,null);
		}
		else if("json".equalsIgnoreCase(lastfix)) //json结果
		{
			setResponseResult(response,"json",obj,null);
		}
		else if("jsonp".equalsIgnoreCase(lastfix) && !"".equals(jsonpFun)) //jsonp结果
		{
			setResponseResult(response,"jsonp",obj,jsonpFun);
		}
		else if(accept !=null && (accept.contains("application/xml") || accept.contains("text/xml"))) //xml结果
		{
			setResponseResult(response,"xml",obj,null);
		}
		else if(accept !=null && (accept.contains("application/json") || accept.contains("text/json")))//json结果
		{
			setResponseResult(response,"json",obj,null);
		}
		else if(accept !=null && (accept.contains("text/javascript") || accept.contains("application/javascript")) && !"".equals(jsonpFun)) //jsonp结果
		{
			setResponseResult(response,"jsonp",obj,jsonpFun);
		}
		else
		{
			setResponseResult(response,"text",obj,null);
		}
	}
	/**
	 * 设置返回数据格式
	 * @param response
	 * @param type
	 * @throws IOException 
	 */
    protected void setResponseResult(HttpServletResponse response,String type,Object obj,String jsopFun) throws IOException
    {
    	response.reset();
    	ResultBaseBean result=null;
    	if(obj instanceof ResultBaseBean )
    	{
    		result=(ResultBaseBean) obj;
    	}
    	else
    	{
    	   result=new ResultBaseBean();
    	   if(obj!=null) result.setData(obj);
    	   result.setSuccess(true);
    	}
    	if("xml".equalsIgnoreCase(type))
    	{
    		aliasPackage(obj);
			response.setContentType("application/xml;charset=utf-8");
			response.getWriter().write(generateXml(result));
			response.getWriter().close();
    	}
    	else if("json".equalsIgnoreCase(type))
    	{
    		response.setContentType("application/json;charset=utf-8");
			response.getWriter().write(generateJson(result));
			response.getWriter().close();
    	}
    	else if("jsonp".equalsIgnoreCase(type))
    	{
    		response.setContentType("application/javascript;charset=utf-8");
			response.getWriter().write(jsopFun+"("+generateJson(result)+")");
			response.getWriter().close();
    	}
    	else if("text".equalsIgnoreCase(type))
    	{
    		response.setContentType("text/plain;charset=utf-8");
			response.getWriter().write(generateJson(result));
			response.getWriter().close();
    	}
    	
    }
	/**
	 * 判断支持情况 
	 */
	@Override
	public boolean supportsReturnType(MethodParameter methodparameter) {
		//ResultFormat rf=methodparameter.getMethodAnnotation(ResultFormat.class);
		//if(rf!=null) return true;
		return true;
	}
	/**
	 * 生成json数据
	 * @param bean
	 * @return
	 */
	public static String generateJson(ResultBaseBean bean)
	{
		String str="";
		SerializerFeature[] features={SerializerFeature.DisableCircularReferenceDetect};
		try {
			str=JSON.toJSONStringWithDateFormat(bean, dateFormat,features);
		} catch (Exception e) {
			logger.info(bean.getData().toString()+" json转换失败");
			e.printStackTrace();
		}
		logger.debug("json:"+str);
		return str;
	}
	/**
	 * 生成xml数据
	 * @param bean
	 * @return
	 */
	public static String generateXml(ResultBaseBean bean)
	{
		String str="<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
		str=str+xstream.toXML(bean);
		logger.debug("xml:"+str);
		return str;		
	}
	/**
	 * 配置xstream
	 */
	protected void configXstream()
	{
		if(xstream!=null) return;
		xstream=new XStream();
		xstream.autodetectAnnotations(true);
		XmlDateConverter dateConverter=new XmlDateConverter(dateFormat);
		xstream.registerConverter(dateConverter);
//		for(String pk:packageNameToEmptys)
//		{
//			xstream.aliasPackage("", pk);
//		}
	}
	/**
	 * 包名别名 row
	 * @param obj
	 */
	protected void aliasPackage(Object obj)
	{
		if(xstream!=null)
		{
			if(obj instanceof PageImpl)
			{
				PageImpl pageImpl=(PageImpl) obj;
				if(!pageImpl.getContent().isEmpty())
				{
					String className=pageImpl.getContent().get(0).getClass().getName();
					xstream.alias("row", pageImpl.getContent().get(0).getClass());
				}
			}
			else if(obj instanceof List)
			{
				List list=(List) obj;
				if(!list.isEmpty()) xstream.alias("row", list.get(0).getClass());
			}
		}
	}
	
	
}
